home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 2 / ACE CD 2.iso / FILES / UTILS / HSBASIC2.DMS / in.adf / HB2Examples1.3.Lha / Examples / IFF_8SVX / iff_8svx.bas < prev    next >
Encoding:
BASIC Source File  |  1994-04-29  |  8.4 KB  |  339 lines

  1. DEFINT A-Z
  2. 'REM $INCLUDE Exec.bh
  3. 'REM $INCLUDE Audio.bc
  4. 'REM $INCLUDE IFFParse.bh
  5. 'REM $INCLUDE utility.bc
  6. 'REM $INCLUDE DOS.bh
  7. 'REM $INCLUDE graphics.bh
  8. 'REM $INCLUDE datatypes/Soundclass.bc
  9. 'REM $INCLUDE datatypes/Pictureclass.bc
  10. 'REM $INCLUDE asl.bh
  11.  
  12. REM $INCLUDE Blib/ExecSupport.bas
  13. REM $INCLUDE BLib/IFFBufIO.bas
  14.  
  15. CONST ID_CHAN& = &h4248414E
  16. CONST NTSC_CLOCK& = 3579545&
  17. CONST PAL_CLOCK& = 3546895&
  18. CONST AIOCNT = 2
  19. CONST MAXSAMPLE&= &h20000&
  20. '
  21. 'Ask the system if we are PAL or NTSC and set clock constant accordingly 
  22. '
  23. FUNCTION getAudioClock&
  24.     STATIC GfxBase&, palflag
  25.  
  26.     getAudioClock& = -1&
  27.     palflag = PAL&
  28.     IF PEEKW(LIBRARY("graphics.library") + lib_Version) >= 39 THEN
  29.         'V39 and above have an early-start independent PAL detection method
  30.  
  31.         palflag = REALLY_PAL&
  32.     END IF
  33.     IF PEEKW(LIBRARY("graphics.library") + DisplayFlags) AND palflag THEN
  34.         getAudioClock& = PAL_CLOCK&
  35.     ELSE
  36.         getAudioClock& = NTSC_CLOCK&
  37.     END IF
  38. END FUNCTION
  39. '
  40. 'Set up the audio I/O block for channel allocation
  41. '
  42. SUB allocateAudioChannels(BYVAL audioIO&, BYVAL audioMP&)
  43.     STATIC ioreq&, whichannel&
  44.  
  45.     ioreq& = audioIO& + ioa_Request
  46.  
  47.     POKEL ioreq& + IORequestio_Message + mn_ReplyPort, audioMP&    ' the address of a reply port
  48.     POKEB ioreq& + IORequestio_Message + mn_Node + ln_Pri, 0    ' neutral priority
  49.     POKEW ioreq& + IORequestio_Command, ADCMD_ALLOCATE&        ' allocate the channels
  50.     POKEB ioreq& + IORequestio_Flags, ADIOF_NOWAIT&
  51.  
  52.     POKEW audioIO& + ioa_AllocKey, 0
  53.  
  54.     whichannel& = &h01020408    ' channel allocation
  55.     POKEL audioIO& + ioa_Data, VARPTR(whichannel&)
  56.     POKEL audioIO& + ioa_Length, 4
  57. END SUB
  58.  
  59.  
  60. SUB OpenAudio
  61. DIM SHARED devopened, port&
  62. STATIC k
  63. STATIC device&
  64. SHARED tclock&
  65. IF devopened THEN EXIT SUB
  66.  
  67. tclock&=getAudioClock&
  68. DIM SHARED  aio&(AIOCNT)
  69.  
  70.  
  71. '
  72. 'Create a reply port so the audio device can reply to our commands
  73. '
  74. port& = CreatePort&(NULL&, 0)
  75. IF port& THEN
  76.     FOR k=0 TO AIOCNT-1
  77.         aio&(k)=CreateExtIO&(port&,IOAudio_sizeof)
  78.         IF aio&(k)=0 THEN CALL CloseAudio: EXIT SUB
  79.     NEXT k
  80.     allocateAudioChannels aio&(0),port&
  81.     device& = OpenDevice&(SADD("audio.device" + CHR$(0)), 0, aio&(0), 0)
  82. ' Clone the flags, channel allocation, etc. into other IOAudio requests
  83.     FOR k=1 TO AIOCNT-1
  84.         CopyMem aio&(0),aio&(k),IOaudio_sizeof
  85.     NEXT k
  86. END IF
  87. IF device&=0 THEN devopened=-1 ELSE CALL CloseAudio
  88. END SUB
  89.  
  90.  
  91. '
  92. ' Close audio device as opened by OpenAudio, null out pointers
  93. SUB CloseAudio
  94. STATIC k
  95. SHARED devopened,port&
  96. ' Note - we know we have no outstanding audio requests */
  97. IF devopened THEN
  98.     CloseDevice aio&(0)
  99.     devopened = 0
  100. END IF
  101. FOR k=0 TO AIOCNT-1
  102.     IF aio&(k) THEN
  103.         DeleteExtIO aio&(k)
  104.         aio&(k) = NULL&
  105.     END IF
  106. NEXT k
  107. IF port& THEN
  108.     DeletePort port&
  109.     port& = NULL&
  110. END IF
  111. END SUB
  112.  
  113.  
  114. FUNCTION LoadSBody(BYVAL iff&,BYVAL vhdr&)
  115. SHARED sbytes&
  116. SHARED sample&
  117. STATIC memtype&
  118. STATIC compression
  119. STATIC cn&
  120.     LoadSBody=0
  121.     cn&=CurrentChunk(iff&)
  122.     IF PEEKL(cn&+cn_type)<>ID_8SVX& OR PEEKL(cn&+cn_ID)<>ID_BODY& THEN
  123.         PRINT "couldn't find BODY chunk"
  124.         EXIT FUNCTION
  125.     END IF
  126.     sbytes& = PEEKL(cn&+cn_Size) - PEEK(cn&+cn_Scan)
  127.     ' if we have to decompress, let's just load it into public mem
  128.     compression= PEEKB(vhdr&+vh_Compression)
  129.     IF compression THEN
  130.         memtype&= MEMF_PUBLIC&
  131.     ELSE
  132.         memtype&= MEMF_CHIP&
  133.     END IF
  134.     sample&=AllocMem(sbytes&,memtype&)
  135.     IF sample&=0 THEN
  136.         PRINT "Not enough memory"
  137.         EXIT FUNCTION
  138.     END IF
  139.     IF ReadChunkBytes(iff&,sample&,sbytes&)<>sbytes& THEN
  140.         PRINT "Can't read whole sample"
  141.         EXIT FUNCTION
  142.     END IF
  143.     
  144.     SELECT CASE compression
  145.     CASE 0
  146.     CASE CMP_FIBDELTA&
  147.         PRINT "Delta compression not yet implemented"
  148.         EXIT FUNCTION
  149.     CASE ELSE
  150.         PRINT "Unknown compression method:";compression
  151.     END SELECT    
  152.     LoadSBody=-1
  153. END FUNCTION
  154.  
  155. SUB UnloadSBody
  156. SHARED sample&, sbytes& 
  157.     IF sample& THEN
  158.         FreeMem sample&,sbytes&
  159.         sample&=0
  160.     END IF
  161.     sbytes&=0
  162. END SUB
  163.  
  164. '
  165. 'The main play sample routine
  166. '
  167. SUB PlaySample(BYVAL vhdr&)
  168. SHARED aio&(1),tclock&
  169. SHARED sbytes&,sample&
  170. STATIC ioreq&,a&,junk&
  171. STATIC period,volume
  172. STATIC req        ' the index of the Audio Request that is currently playing
  173. STATIC reqn        ' the index of the next request that we are creating
  174. STATIC sampleptr&    ' where we are playing from
  175. STATIC bytesleft&    ' bytes still to play
  176.  
  177.     period= tclock&/PEEKW(vhdr&+vh_samplespersec)
  178.     volume=MAX(PEEKL(vhdr&+vh_volume)*64/&h10000,64)
  179.  
  180.     sampleptr&=sample&
  181.     bytesleft&=sbytes&    
  182.  
  183.     a&=aio&(0)
  184.     ioreq&=a&+ioa_Request
  185.  
  186.     POKEW ioreq& + IORequestio_Command    , CMD_WRITE&
  187.     POKEB ioreq& + IORequestio_Flags    , ADIOF_PERVOL&
  188.     POKEL a&     + ioa_Data                , sampleptr&
  189.     POKEL a&     + ioa_Length            , MIN(bytesleft&, MAXSAMPLE&)
  190.     POKEW a&     + ioa_Period            , period
  191.     POKEW a&     + ioa_Volume             , volume
  192.     POKEW a&     + ioa_Cycles            , 1
  193.  
  194. ' Send the command to start a sound using BeginIO()
  195.     BEGINIO a&
  196.     req=0            ' the first one is now playing
  197.  
  198.     DO
  199.         bytesleft&=bytesleft&-MAXSAMPLE&
  200.         IF bytesleft&<=0 THEN EXIT LOOP
  201.         sampleptr&=sampleptr&+MAXSAMPLE&
  202.  
  203.         reqn = req XOR 1        ' alternate IO Blocks 0 and 1
  204.         a&=aio&(reqn)
  205.         ioreq&=a&+ ioa_Request
  206.  
  207.         POKEW ioreq& + IORequestio_Command    , CMD_WRITE&
  208.         POKEB ioreq& + IORequestio_Flags    , ADIOF_PERVOL&
  209.         POKEL a&     + ioa_Data                , sampleptr&
  210.         POKEL a&     + ioa_Length            , MIN(bytesleft&,MAXSAMPLE&)
  211.         POKEW a&     + ioa_Period            , period
  212.         POKEW a&     + ioa_Volume             , volume
  213.         POKEW a&     + ioa_Cycles            , 1
  214.         BEGINIO a&
  215.  
  216.         junk&= WaitIO(aio&(req))        ' wait for the previous request to finish
  217.  
  218.         req    =reqn            ' the one we've just started is now playing
  219.         
  220.     LOOP    
  221. ' wait for the final (or only!) io request to finish        
  222.     junk&= WaitIO(aio&(req))
  223.  
  224. PRINT "done!"
  225. END SUB
  226.  
  227.  
  228.  
  229. SUB PlayFile (filename$)
  230. STATIC iff&, stream&, junk&, sp&, vhdr&, camg&, bm&, screenptr&, w, h, depth
  231. SHARED sbytes&
  232. iff& = AllocIFF&
  233. IF iff& THEN
  234.     stream& = xOpen&(SADD(filename$ + CHR$(0)), MODE_OLDFILE&)
  235.     IF stream& THEN
  236.         POKEL iff& + iff_Stream, stream&        'connect the DOS stream
  237.  
  238.         IF PEEKW(LIBRARY("dos.library") + lib_Version) >= 36 THEN
  239.         'for WB2 and above, use the buffered DOS I/O calls
  240.             junk& = SetVBuf&(stream&, NULL&, BUF_FULL&, 8192)
  241.             initIFFasBufferedDOS iff&
  242.         ELSE
  243.         'fall back for 1.3 (if you have 1.3 iffparse.library)
  244.             InitIFFasDos iff&
  245.         END IF
  246.  
  247.         IF OpenIFF&(iff&, IFFF_READ&) = 0 THEN
  248.             IF PropChunk&(iff&, ID_8SVX&, ID_VHDR&) = 0 AND _
  249.               StopChunk&(iff&, ID_8SVX&, ID_BODY&) = 0 AND _
  250.               ParseIFF(iff&, IFFPARSE_SCAN&) = 0 THEN
  251.  
  252.                 'look for a VHDR stored property
  253.                 sp& = FindProp&(iff&, ID_8SVX&, ID_VHDR&)
  254.                 vhdr& = 0
  255.                 IF sp& THEN    vhdr& = PEEKL(sp& + sp_Data)
  256.                 IF vhdr& THEN
  257.                     PRINT "VHDR info:"
  258.                     PRINT "oneShotHiSamples = ", PEEKL(vhdr&+vh_oneShotHiSamples)
  259.                     PRINT "repeatHiSamples = ", PEEKL(vhdr&+vh_repeatHiSamples) 
  260.                     PRINT "samplesPerHiCycle = ", PEEKL(vhdr&+vh_samplesPerHiCycle)
  261.                     PRINT "samplesPerSec = ", PEEKW(vhdr&+vh_samplesPerSec)
  262.                     PRINT "Octaves = ", PEEKB(vhdr&+vh_Octaves)
  263.                     PRINT "Compression = ", PEEKB(vhdr&+vh_Compression)
  264.                     PRINT "volume = ", HEX$(PEEKL(vhdr&+vh_volume))
  265.                     IF PEEKB(vhdr&+vh_octaves)=1 AND _ 
  266.                         PEEKW(vhdr&+vh_samplesPerSec)<>0 AND _
  267.                         PEEKL(Vhdr&+vh_oneShotHiSamples)<>0 AND _
  268.                         PEEKL(Vhdr&+vh_repeatHiSamples)=0 THEN
  269.                     ' its a simple sampled sound rather than a musical instrument
  270.                         IF LoadSBody(iff&,vhdr&) THEN
  271.                             PRINT "loaded";sbytes&; "bytes of sample"
  272.                             PlaySample vhdr&
  273.                         END IF
  274.                         UnLoadSBody    ' we must call this even if we failed to load
  275.                     ELSE
  276.                         PRINT "Its not a simple sound"
  277.                     END IF
  278.                 ELSE
  279.                     PRINT "No VHDR"
  280.                 END IF
  281.             ELSE
  282.                 PRINT "Can't find VHDR and/or BODY"
  283.             END IF
  284.             
  285.             CloseIFF iff&
  286.             junk& = xClose(PEEKL(iff& + iff_Stream))
  287.             FreeIFF iff&
  288.         END IF
  289.     ELSE
  290.         PRINT filename$;" not found"
  291.     END IF
  292. END IF
  293. END SUB
  294.  
  295. '
  296. ' Start the main program
  297. '
  298. LIBRARY OPEN "dos.library"
  299. LIBRARY OPEN "graphics.library"
  300. LIBRARY OPEN "iffparse.library"
  301. LIBRARY OPEN "exec.library"
  302.  
  303. OpenAudio
  304. IF devopened=0 THEN PRINT "Can't open audio":STOP
  305.  
  306. IF LEN(COMMAND$) then
  307.     ' we have a command line - play the file
  308.         PlayFile COMMAND$ 
  309. ELSE
  310. ' No command line use the ASL file requester (only works on WB2 and up)
  311.     LIBRARY OPEN "asl.library"
  312.     DIM frtags&(20)
  313.     TAGLIST VARPTR(frtags&(0)),ASLFR_TitleText&,"Sound Sample Info", _
  314.             ASLFR_InitialFile&,"", _
  315.             ASLFR_InitialDrawer&, CURDIR$, _
  316.             TAG_DONE&
  317.  
  318.     fr&=AllocAslRequest&(ASL_FileRequest&,VARPTR(frtags&(0)))
  319.     IF fr& THEN
  320.         DO
  321.             IF AslRequest&(fr&,0) THEN
  322.     ' a file name was entered to the file requester, so build the filename
  323.     ' from it and play the file
  324.                 filename$=PEEK$(PEEKL(fr&+fr_Drawer))
  325.                 IF RIGHT$(filename$,1)<>":" THEN
  326.                     filename$=filename$+"/"
  327.                 END IF
  328.                 filename$=filename$+PEEK$(PEEKL(fr&+fr_File))
  329.                 PlayFile filename$
  330.             ELSE
  331.                 EXIT LOOP
  332.             END IF
  333.         LOOP
  334.         FreeASlRequest fr&
  335.     END IF
  336. END IF
  337. CloseAudio
  338.